/*
** Large portions of this file come from the SQLite sources. - GJ
*/

/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.240 2008/01/22 23:37:10 drh Exp $
*/

// The name of the generated procedure that implements the parser
// is as follows:
%name edbParser

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
//
%token_type {Token}
%default_type {Token}


// The generated parser function takes a 4th argument as follows:
%extra_argument {edbParseContext *pParse}

// This code runs whenever there is a syntax error
//
%syntax_error {
//  assert( TOKEN.z[0] );  /* The tokenizer always gives us a token */
//  sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
	printf("Syntax error\n");
	pParse->parseError = 1;
}
%stack_overflow {
//  sqlite3ErrorMsg(pParse, "parser stack overflow");
//  pParse->parseError = 1;
	printf("parser stack overflow\n");
}


%include {
#include "edb_main.h"
#include "edb_msg_parser.h"

} // end %include


// Input is a single SQL command
input ::= cmdlist.
cmdlist ::= cmdlist ecmd.
cmdlist ::= ecmd.
cmdx ::= cmd.			{ edbFinishCoding(pParse); }
ecmd ::= SEMI.
ecmd ::= explain cmdx SEMI.
explain ::= .			{ edbBeginParse(pParse, 0); }
explain ::= EXPLAIN.	{ edbBeginParse(pParse, 1); }

// TODO STILL:
input ::= DOT INTEGER FLOAT VARIABLE REGISTER BLOB. { }
input ::= INTO. {}

///////////////////// The CREATE DOMAIN statement ////////////////////////////
//
cmd ::= CREATE DOMAIN domain_nm(N). {
	edbCreateDomain(pParse,N,0);
}
cmd ::= CREATE DOMAIN domain_nm(N) LP attributelist(A) RP. {
	edbCreateDomain(pParse,N,A);	
}

%type attributelist {AttrList *}
%destructor attributelist {edbAttrListDestroy($$);}

attributelist(A) ::= attributelist(X) COMMA attribute(Y). { A = edbAppendAttrList(pParse, X, Y ); }
attributelist(A) ::= attribute(Y). { A = edbAppendAttrList(pParse, 0, Y ); }

%type attribute { AttrValue * }
%destructor attribute { edbDestroyAttrValue($$); }

attribute(A) ::= nm(X) COLON nm(Y). { A = edbCreateAttrValue(pParse, X, Y); }
attribute(A) ::= nm(X). { A = edbCreateAttrValue(pParse, X, 0 ); }
attribute(A) ::= nm(X) COLON VARIABLE(Y). { A = edbCreateAttrValue(pParse, X, edbResolveVariable(pParse, &Y) ); }
attribute(A) ::= nm(X) COLON INTEGER(Y). { A = edbCreateAttrValueFromInteger(pParse, X, &Y); }

///////////////////// The SYNC DOMAIN statement ////////////////////////////
//
/*
cmd ::= sync_domain.
sync_domain ::= SYNC DOMAIN domain_nm(N) UP sync_as(M).	{ edbSyncDomainUp(pParse,N,M); }
sync_domain ::= SYNC DOMAIN domain_nm(N) DOWN sync_as(M).	{ edbSyncDomainDown(pParse,N,M); }
sync_domain ::= SYNC DOMAIN domain_nm(N) DELETE.	{ edbSyncDomainDelete(pParse,N,0); }
%type sync_as {Token *}
sync_as(A) ::= . 									{ A = 0; }
sync_as(A) ::= AS nm(X). 							{ A = X; }
*/

///////////////////// The DROP DOMAIN statement ////////////////////////////
//
cmd ::= drop_domain.
drop_domain ::= DROP DOMAIN domain_nm(N). {
	edbDropDomain(pParse,N);
}

/////////////////////////// The DELETE statement /////////////////////////////
//
cmd ::= DELETE selattrlist(W) FROM domain_nm(N) where_opt(Y). {edbDeleteFrom(pParse,N,Y,W);}

%type where_opt {Expr*}
//%destructor where_opt {sqlite3ExprDelete($$);}

where_opt(A) ::= .                    {A = 0;}
where_opt(A) ::= WHERE expr(X).       {A = X;}


///////////////////// The INSERT statement ////////////////////////////
//
cmd ::= INSERT INTO domain_nm(N) VALUES LP attributelist(A) RP where_opt(Y). { edbInsert(pParse, N, A, Y ); }


///////////////////// The SELECT statement ////////////////////////////
//
cmd ::= SELECT selattrlist(W) FROM domain_nm(X) where_opt(Y) groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). { edbSelect(pParse, W,X,Y,P,Q,Z,L); }

%type selattrlist {AttrList *}
%destructor selattrlist {edbAttrListDestroy($$);}
selattrlist(A) ::= STAR.				{A = 0;}
selattrlist(A) ::= attributelist(X).	{A = X;}


// TODO eventually:
%type groupby_opt {Token *}
groupby_opt(A) ::= .					{A = 0;}
groupby_opt(A) ::= GROUP BY nm(X).		{A = 0;(void)X;}

%type having_opt {Token *}
having_opt(A)  ::= .					{A = 0;}
having_opt(A)  ::= HAVING expr(X).		{A = 0;(void)X;}



%type sortorderlist {AttrList *}
%destructor sortorderlist {edbAttrListDestroy($$);}

sortorderlist(A) ::= sortorderlist(X) COMMA sortorder(Y). { A = edbAppendAttrList(pParse, X, Y ); }
sortorderlist(A) ::= sortorder(Y). { A = edbAppendAttrList(pParse, 0, Y ); }

%type sortorder { AttrValue * }
%destructor sortorder { edbDestroyAttrValue($$); }

sortorder(A) ::= nm(X) COLON ASC|DESC(Y). { A = edbCreateAttrValue(pParse, X, &Y); }
sortorder(A) ::= nm(X). { A = edbCreateAttrValue(pParse, X, 0 ); }

%type orderby_opt {AttrList *}
orderby_opt(A) ::= .								{A = 0;}
orderby_opt(A) ::= ORDER BY sortorderlist(X).		{A = X;}




%type limit_opt {AttrList *}
limit_opt(A)   ::= .									{A = 0;}
limit_opt(A)   ::= LIMIT INTEGER(X).					{
	A = edbAppendAttrList(pParse, 0, edbCreateAttrValueCStr(pParse, "limit", &X));
}
limit_opt(A)   ::= LIMIT INTEGER(X) OFFSET INTEGER(Y).	{
	A = edbAppendAttrList(pParse, 0, edbCreateAttrValueCStr(pParse, "limit", &X));
	A = edbAppendAttrList(pParse, A, edbCreateAttrValueCStr(pParse, "offset", &Y));
}
//limit_opt(A)   ::= LIMIT expr(X) COMMA expr(Y).		{A = 0;X;Y;}
//%type sortorder {int}
//sortorder(A) ::= ASC.           {A = 0;}
//sortorder(A) ::= DESC.          {A = 1;}
//sortorder(A) ::= .              {A = 0;}

%type domain_nm {Token *}
%destructor domain_nm { edbDestroyToken($$); }

domain_nm(A) ::= VARIABLE(X).   {A = edbResolveVariable(pParse, &X);}
domain_nm(A) ::= nm(X).			{A = X;}

%type nm {Token *}
%destructor nm { edbDestroyToken($$); }
nm(A) ::= ID(X).         {A = edbValueFromID(pParse,&X);}
nm(A) ::= STRING(X).     {A = edbDequote(pParse,&X);}




// Define operator precedence early so that this is the first occurance
// of the operator tokens in the grammer.  Keeping the operators together
// causes them to be assigned integer values that are close together,
// which keeps parser tables smaller.
//
// The token values assigned to these symbols is determined by the order
// in which lemon first sees them.  It must be the case that ISNULL/NOTNULL,
// NE/EQ, GT/LE, and GE/LT are separated by only a single value.  See
// the sqlite3ExprIfFalse() routine for additional information on this
// constraint.
//
%left OR.
%left AND.
%right NOT.
%left IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
%left GT LE LT GE.
%right ESCAPE.
%left BITAND BITOR LSHIFT RSHIFT.
%left PLUS MINUS.
%left STAR SLASH REM.
%left CONCAT.
%left COLLATE.
%right UMINUS UPLUS BITNOT.





/////////////////////////// Expression Processing /////////////////////////////
//
%type expr {Expr*}
//%destructor expr {sqlite3ExprDelete($$);}
%type term {Expr*}
//%destructor term {sqlite3ExprDelete($$);}

expr(A) ::= term(X).                       {A = X;}

term(A) ::= STRING(X).                     {A = edbExpr(pParse, @X, 0, 0, edbDequote(pParse,&X));}
term(A) ::= INTEGER|FLOAT|BLOB(X).         {A = edbExpr(pParse, @X, 0, 0, &X);}
term(A) ::= VARIABLE(X).                   {A = edbExpr(pParse, @X, 0, 0, edbResolveVariable(pParse, &X));}
expr(A) ::= ID(X).                         {A = edbExpr(pParse, TK_ID, 0, 0, &X);}

expr(A) ::= expr(X) AND(OP) expr(Y).       {A = edbExpr(pParse,@OP,X,Y,0);}
expr(A) ::= expr(X) OR(OP) expr(Y).        {A = edbExpr(pParse,@OP,X,Y,0);}
expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y).
                                           {A = edbExpr(pParse,@OP,X,Y,0);}
expr(A) ::= expr(X) EQ|NE(OP) expr(Y).     {A = edbExpr(pParse,@OP,X,Y,0);}
expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
                                           {A = edbExpr(pParse,@OP,X,Y,0);}
expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y).{A = edbExpr(pParse,@OP,X,Y,0);}
expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y).
                                           {A = edbExpr(pParse,@OP,X,Y,0);}
expr(A) ::= expr(X) CONCAT(OP) expr(Y).    {A = edbExpr(pParse,@OP,X,Y,0);}

expr(A) ::= ID(X) LP attributelist(Y) RP. {A = edbExprFunction(pParse,&X,Y);}


